package com.jorado.redis;

import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 新版的Redis操作类(对于数值类型返回值，返回的是Long等)
 */
public class RedisClient implements Closeable {

    private RedisClientInterface redisClient;

    protected RedisClient() {

    }

    /**
     * redis处理类的构造函数
     *
     * @param redisClusters redis连接字符串
     */
    public RedisClient(String redisClusters) {
        this(redisClusters, false, Long.MIN_VALUE);
    }

    /**
     * redis处理类的构造函数
     *
     * @param redisClusters redis连接字符串
     * @param fuseTime      熔断时间(毫秒为单位)
     */
    public RedisClient(String redisClusters, long fuseTime) {
        this(redisClusters, true, fuseTime);
    }

    /**
     * redis处理类的构造函数
     *
     * @param redisClusters   redis连接字符串
     * @param connectTimeout  连接超时时间
     * @param socketTimeout   读取超时的时间
     * @param maxRedirections 最大重试次数
     */
    public RedisClient(String redisClusters, int connectTimeout, int socketTimeout, int maxRedirections) {
        this(redisClusters, connectTimeout, socketTimeout, maxRedirections, false, Long.MIN_VALUE);
    }

    /**
     * redis处理类的构造函数
     *
     * @param redisClusters   redis连接字符串
     * @param connectTimeout  连接超时时间
     * @param socketTimeout   读取超时的时间
     * @param maxRedirections 最大重试次数
     * @param fuseTime        熔断时间(毫秒为单位)
     */
    public RedisClient(String redisClusters, int connectTimeout, int socketTimeout, int maxRedirections,
                       long fuseTime) {
        this(redisClusters, connectTimeout, socketTimeout, maxRedirections, true, fuseTime);
    }

    /**
     * redis处理类的构造函数
     *
     * @param redisClusters   redis连接字符串
     * @param connectTimeout  连接超时时间
     * @param socketTimeout   读取超时的时间
     * @param maxRedirections 最大重试次数
     * @param maxTotal        连接池配置参数(最大的连接数)
     * @param maxIdle         连接池配置参数(最大空闲连接)
     * @param minIdle         连接池配置参数(最少空闲连接)
     * @param maxWaitMillis   获取连接池中连接的最大等待时间
     */
    public RedisClient(String redisClusters, int connectTimeout, int socketTimeout, int maxRedirections, int maxTotal,
                       int maxIdle, int minIdle, int maxWaitMillis) {
        this(redisClusters, connectTimeout, socketTimeout, maxRedirections, maxTotal, maxIdle, minIdle, maxWaitMillis,
                false, Long.MIN_VALUE);
    }

    /**
     * redis处理类的构造函数
     *
     * @param redisClusters   redis连接字符串
     * @param connectTimeout  连接超时时间
     * @param socketTimeout   读取超时的时间
     * @param maxRedirections 最大重试次数
     * @param maxTotal        连接池配置参数(最大的连接数)
     * @param maxIdle         连接池配置参数(最大空闲连接)
     * @param minIdle         连接池配置参数(最少空闲连接)
     * @param maxWaitMillis   获取连接池中连接的最大等待时间
     * @param fuseTime        熔断时间(毫秒为单位)
     */

    public RedisClient(String redisClusters, int connectTimeout, int socketTimeout, int maxRedirections, int maxTotal,
                       int maxIdle, int minIdle, int maxWaitMillis, long fuseTime) {
        this(redisClusters, connectTimeout, socketTimeout, maxRedirections, maxTotal, maxIdle, minIdle, maxWaitMillis,
                true, fuseTime);
    }

    /**
     * redis处理类的构造函数
     *
     * @param redisClusters redis连接字符串
     * @param isFuse        熔断标志
     * @param fuseTime      熔断时间(毫秒为单位)
     */
    private RedisClient(final String redisClusters, final boolean isFuse, final long fuseTime) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        this.redisClient = (RedisClientInterface) Proxy.newProxyInstance(classLoader,
                new Class<?>[]{RedisClientInterface.class},
                new RedisClientProxy(new RedisClientImpl(redisClusters, isFuse, fuseTime)));
    }

    /**
     * redis处理类的构造函数
     *
     * @param redisClusters   redis连接字符串
     * @param connectTimeout  连接超时时间
     * @param socketTimeout   读取超时的时间
     * @param maxRedirections 最大重试次数
     * @param isFuse          熔断标志
     * @param fuseTime        熔断时间(毫秒为单位)
     */
    private RedisClient(final String redisClusters, final int connectTimeout, final int socketTimeout,
                        final int maxRedirections, final boolean isFuse, final long fuseTime) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        this.redisClient = (RedisClientInterface) Proxy.newProxyInstance(classLoader,
                new Class<?>[]{RedisClientInterface.class}, new RedisClientProxy(new RedisClientImpl(redisClusters,
                        connectTimeout, socketTimeout, maxRedirections, isFuse, fuseTime)));
    }

    /**
     * redis处理类的构造函数
     *
     * @param redisClusters   redis连接字符串
     * @param connectTimeout  连接超时时间
     * @param socketTimeout   读取超时的时间
     * @param maxRedirections 最大重试次数
     * @param maxTotal        连接池配置参数(最大的连接数)
     * @param maxIdle         连接池配置参数(最大空闲连接)
     * @param minIdle         连接池配置参数(最少空闲连接)
     * @param maxWaitMillis   获取连接池中连接的最大等待时间
     * @param isFuse          熔断标志
     * @param fuseTime        熔断时间(毫秒为单位)
     */

    private RedisClient(final String redisClusters, final int connectTimeout, final int socketTimeout,
                        final int maxRedirections, final int maxTotal, final int maxIdle, final int minIdle,
                        final int maxWaitMillis, final boolean isFuse, final long fuseTime) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        this.redisClient = (RedisClientInterface) Proxy.newProxyInstance(classLoader,
                new Class<?>[]{RedisClientInterface.class},
                new RedisClientProxy(new RedisClientImpl(redisClusters, connectTimeout, socketTimeout, maxRedirections,
                        maxTotal, maxIdle, minIdle, maxWaitMillis, isFuse, fuseTime)));
    }

    @Override
    public void close() throws IOException {
        getRedisClient().close();
    }

    /**
     * 执行Redis的SETEX命令
     *
     * @param key
     * @param seconds
     * @param value
     * @return
     */
    public String setex(final String key, final int seconds, final String value) {
        return getRedisClient().setex(key, seconds, value);
    }

    /**
     * 执行Redis的SET命令
     *
     * @param key
     * @param value
     * @return
     */
    public String set(final String key, final String value) {
        return getRedisClient().set(key, value);
    }

    /**
     * @param key   redis key
     * @param value redis value
     * @param nxxx  optional values are NX(not exist),XX(exist)
     * @param expx  optional values are EX(expire time in second), PX(expire time in millisecond)
     * @param time  the expire time
     * @return
     */
    public String set(final String key, final String value, final String nxxx, final String expx, final long time) {
        return getRedisClient().set(key, value, nxxx, expx, time);
    }

    /**
     * @param key   redis key
     * @param value redis value
     * @param expx  optional values are EX(expire time in second), PX(expire time in millisecond)
     * @param time  the expire time
     * @return
     */
    public String set(final String key, final String value, final String expx, final long time) {
        return getRedisClient().set(key, value, expx, time);
    }

    /**
     * 以秒为单位的超时时间设置key的过期(等同于setex命令)
     *
     * @param key   redis命令的key
     * @param value redis命令的value
     * @param time  过期时间，单位是秒
     * @return
     */
    public String setEx(String key, String value, int time) {
        return getRedisClient().setEx(key, value, time);
    }

    /**
     * 以毫秒为单位的超时时间设置key的过期(等同于psetex命令)
     *
     * @param key   redis命令的key
     * @param value redis命令的value
     * @param time  过期时间，单位是毫秒
     * @return
     */
    public String pSetEx(String key, String value, long time) {
        return getRedisClient().pSetEx(key, value, time);
    }

    /**
     * 执行Redis的GET命令
     *
     * @param key
     * @return
     */
    public String get(final String key) {
        return this.getRedisClient().get(key);
    }

    /**
     * 执行Redis的DEL命令
     *
     * @param key
     * @return
     */
    public Long del(String key) {
        return this.getRedisClient().del(key);
    }

    /**
     * 执行Redis的GETSET命令
     *
     * @param key
     * @param value
     * @return
     */
    public String getSet(final String key, final String value) {
        return this.getRedisClient().getSet(key, value);
    }

    /**
     * 执行Redis的SETNX命令
     *
     * @param key
     * @param value
     * @return
     */
    public Long setnx(final String key, final String value) {
        return getRedisClient().setnx(key, value);
    }

    /**
     * 执行Redis的DECRBY命令
     *
     * @param key
     * @param integer
     * @return
     */
    public Long decrBy(final String key, final long integer) {
        return this.getRedisClient().decrBy(key, integer);
    }

    /**
     * 执行Redis的DECR命令
     *
     * @param key
     * @return
     */
    public Long decr(final String key) {
        return this.getRedisClient().decr(key);
    }

    /**
     * 执行Redis的INCR命令
     *
     * @param key
     * @return
     */
    public Long incr(final String key) {
        return this.getRedisClient().incr(key);
    }

    /**
     * 执行Redis的INCRBY命令
     *
     * @param key
     * @param integer
     * @return 成功的情况下返回该键递增integer后的值，出现异常的情况下返回NULL
     */
    public Long incrBy(final String key, final long integer) {
        return this.getRedisClient().incrBy(key, integer);
    }

    /**
     * 执行Redis的EXPIRE命令
     *
     * @param key
     * @param seconds
     * @return
     */
    public Long expire(final String key, final int seconds) {
        return this.getRedisClient().expire(key, seconds);
    }

    /**
     * 执行Redis的PERSIST命令
     *
     * @param key
     * @return
     */
    public Long persist(final String key) {
        return this.getRedisClient().persist(key);
    }

    /**
     * 执行Redis的PEXPIREAT命令
     *
     * @param key
     * @param millisecondsTimestamp
     * @return
     */
    public Long pexpireAt(final String key, final long millisecondsTimestamp) {
        return this.getRedisClient().pexpireAt(key, millisecondsTimestamp);
    }

    /**
     * 执行Redis的PEXPIRE命令
     *
     * @param key
     * @param milliseconds
     * @return
     */
    public Long pexpire(final String key, final long milliseconds) {
        return this.getRedisClient().pexpire(key, milliseconds);
    }

    /* Hash(哈希表) 命令 */

    /**
     * 执行Redis的HDEL命令
     *
     * @param key
     * @param field
     * @return
     */
    public Long hdel(final String key, final String... field) {
        return this.getRedisClient().hdel(key, field);
    }

    /**
     * 执行Redis的HSET命令
     *
     * @param key
     * @param field
     * @param value
     * @return 如果哈希表中该field存在，返回1， 否则返回0， 异常情况下返回0
     */
    public Long hset(final String key, final String field, final String value) {
        return this.getRedisClient().hset(key, field, value);
    }

    /**
     * 执行Redis的HGETALL命令
     *
     * @param key
     * @return
     */
    public Map<String, String> hgetAll(final String key) {
        return this.getRedisClient().hgetAll(key);
    }

    /**
     * 执行Redis的HMSET命令
     *
     * @param key
     * @param fields
     * @return
     */
    public String hmset(final String key, final Map<String, String> hash) {
        return this.getRedisClient().hmset(key, hash);
    }

    /**
     * 执行Redis的HGET命令
     *
     * @param key
     * @param field
     * @return
     */
    public String hget(final String key, final String field) {
        return this.getRedisClient().hget(key, field);
    }

    /**
     * 执行Redis的HVALS命令
     *
     * @param key
     * @param field
     * @param value
     * @return
     */
    public List<String> hvals(final String key) {
        return this.getRedisClient().hvals(key);
    }

    /**
     * 执行Redis的HINCRBY命令
     *
     * @param key
     * @param field
     * @param value
     * @return
     */
    public Long hincrBy(final String key, final String field, final long value) {
        return this.getRedisClient().hincrBy(key, field, value);
    }

    /**
     * 执行Redis的HKEYS命令
     *
     * @param key
     * @return
     */
    public Set<String> hkeys(final String key) {
        return this.getRedisClient().hkeys(key);
    }

    /**
     * 执行Redis的HMGET命令
     *
     * @param key
     * @param fields
     * @return
     */
    public List<String> hmget(final String key, final String... fields) {
        return this.getRedisClient().hmget(key, fields);
    }

    /**
     * 执行Redis的HEXISTS命令
     *
     * @param key
     * @param field
     * @return
     */
    public Boolean hexists(final String key, final String field) {
        return this.getRedisClient().hexists(key, field);
    }

    /**
     * 执行Redis的HLEN命令
     *
     * @param key
     * @return
     */
    public Long hlen(final String key) {
        return this.getRedisClient().hlen(key);
    }

    /**
     * 执行Redis的HSETNX命令
     *
     * @param key
     * @param field
     * @param value
     * @return
     */
    public Long hsetnx(final String key, final String field, final String value) {
        return this.getRedisClient().hsetnx(key, field, value);
    }

    /* List(列表) 命令 */

    /**
     * 执行Redis的BLPOP命令
     *
     * @param timeout
     * @param key
     * @return
     */
    public List<String> blpop(final int timeout, final String key) {
        return this.getRedisClient().blpop(timeout, key);
    }

    /**
     * 执行Redis的BRPOP命令
     *
     * @param timeout
     * @param key
     * @return
     */
    public List<String> brpop(final int timeout, final String key) {
        return this.getRedisClient().brpop(timeout, key);
    }

    /**
     * 执行Redis的LPUSH命令
     *
     * @param key
     * @param string
     * @return
     */
    public Long lpush(final String key, final String... string) {
        return this.getRedisClient().lpush(key, string);
    }

    /**
     * 执行Redis的LREM命令, 根据参数 count 的值，移除列表中与参数 value 相等的元素
     *
     * @param key
     * @param count count > 0 : 从表头开始向表尾搜索，移除与 value 相等的元素，数量为 count, count < 0 :
     *              从表尾开始向表头搜索，移除与 value 相等的元素，数量为 count 的绝对值, count = 0 : 移除表中所有与
     *              value 相等的值
     * @param value
     * @return
     */
    public Long lrem(final String key, final long count, final String value) {
        Long result = this.getRedisClient().lrem(key, count, value);
        if (result == null) {
            return 0L;
        }
        return result.longValue();
    }

    /**
     * 执行Redis的LLEN命令
     *
     * @param key
     * @return
     */
    public Long llen(final String key) {
        return this.getRedisClient().llen(key);
    }

    /**
     * 执行Redis的LINDEX命令
     *
     * @param key
     * @param index
     * @return
     */
    public String lindex(String key, long index) {
        return this.getRedisClient().lindex(key, index);
    }

    /**
     * 执行Redis的LPOP命令
     *
     * @param key
     * @return
     */
    public String lpop(final String key) {
        return this.getRedisClient().lpop(key);
    }

    /**
     * 执行Redis的LPUSHX命令(LPUSHX根本不支持一次性多个值，不清楚jedis为什么这样定义)， 将值 value 插入到列表 key
     * 的表头， 当且仅当 key 存在并且是一个列表， 和 LPUSH 命令相反，当 key 不存在时， LPUSHX 命令什么也不做
     *
     * @param key
     * @param string
     * @return USHX 命令执行之后，表的长度, 当 key 不存在时和异常情况下返回0
     */
    public Long lpushx(final String key, final String... string) {
        Long result = 0L;
        for (String str : string) {
            Long value = this.getRedisClient().lpushx(key, str);
            if (value == null) {
                // 出现异常时
                return null;
            } else if (value.longValue() == 0) {
                // 键不存在的情况
                return 0L;
            } else if (result.longValue() < value.longValue()) {
                result = value;
            }
        }
        return result;
    }

    /**
     * 执行Redis的LRANGE命令
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public List<String> lrange(final String key, final long start, final long end) {
        return this.getRedisClient().lrange(key, start, end);
    }

    /**
     * 执行Redis的LSET命令
     *
     * @param key
     * @param index
     * @param value
     * @return
     */
    public String lset(final String key, final long index, final String value) {
        return this.getRedisClient().lset(key, index, value);
    }

    /**
     * 执行Redis的LTRIM命令
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public String ltrim(final String key, final long start, final long end) {
        return this.getRedisClient().ltrim(key, start, end);
    }

    /**
     * 执行Redis的RPUSHX命令, 将值 value 插入到列表 key 的表尾，当且仅当 key 存在并且是一个列表, 和 RPUSH
     * 命令相反，当 key 不存在时， RPUSHX 命令什么也不做
     *
     * @param key
     * @param string
     * @return
     */
    public Long rpushx(final String key, final String... string) {
        Long result = 0L;
        for (String str : string) {
            Long value = this.getRedisClient().rpushx(key, str);
            if (value != null) {
                if (value == 0L) {
                    // 这种情况对应的是键不存在
                    break;
                } else if (result < value) {
                    result = value;
                }
            } else {
                return null;
            }
        }
        return result.longValue();
    }

    /**
     * 执行Redis的RPUSH命令
     *
     * @param key
     * @param string
     * @return
     */
    public Long rpush(final String key, final String... string) {
        return this.getRedisClient().rpush(key, string);
    }

    /**
     * 执行Redis的LINSERT命令,where=before
     *
     * @param key
     * @param pivot
     * @param value
     * @return
     */
    public Long lbeforeinsert(final String key, final String pivot, final String value) {
        return this.getRedisClient().lbeforeinsert(key, pivot, value);
    }

    /**
     * 执行Redis的LINSERT命令,where=after
     *
     * @param key
     * @param pivot
     * @param value
     * @return
     */
    public Long lafterinsert(final String key, final String pivot, final String value) {
        return this.getRedisClient().lafterinsert(key, pivot, value);
    }

    /**
     * 执行Redis的RPOP命令
     *
     * @param key
     * @return
     */
    public String rpop(final String key) {
        return this.getRedisClient().rpop(key);
    }

    /* Set(集合)命令 */

    /**
     * 执行Redis的SADD命令 将一个或多个 member 元素加入到集合 key 当中，已经存在于集合的 member 元素将被忽略
     *
     * @param key
     * @param member
     * @return 被添加到集合中的新元素的数量，不包括被忽略的元素
     */
    public Long sadd(final String key, final String... member) {
        Long result = this.getRedisClient().sadd(key, member);
        if (result == null) {
            return 0L;
        }
        return result.longValue();
    }

    /**
     * 执行Redis的SCARD命令 返回集合 key 的基数(集合中元素的数量)
     *
     * @param key
     * @return 集合的基数, 当 key 不存在时，返回 0, 出现异常的情况下返回0
     */
    public Long scard(final String key) {
        return this.getRedisClient().scard(key);
    }

    /**
     * 执行Redis的SMEMBERS命令
     *
     * @param key
     * @param member
     * @return
     */
    public Set<String> smembers(final String key) {
        return this.getRedisClient().smembers(key);
    }

    /**
     * 执行Redis的SREM命令
     *
     * @param key
     * @param member
     * @return
     */
    public Long srem(final String key, final String... member) {
        return this.getRedisClient().srem(key, member);
    }

    /**
     * 执行Redis的SPOP命令
     *
     * @param key
     * @param member
     * @return
     */
    public String spop(final String key) {
        return this.getRedisClient().spop(key);
    }

    /**
     * 执行Redis的SISMEMBER命令
     *
     * @param key
     * @param member
     * @return
     */
    public Boolean sismember(final String key, final String member) {
        return this.getRedisClient().sismember(key, member);
    }

    /**
     * 执行Redis的SRANDMEMBER命令
     *
     * @param key
     * @param member
     * @return
     */
    public String srandmember(final String key) {
        return this.getRedisClient().srandmember(key);
    }

    /* Key(键)命令 */

    /**
     * 执行Redis的TYPE命令
     *
     * @param key
     * @return
     */
    public String type(final String key) {
        return this.getRedisClient().type(key);
    }

    /**
     * 执行Redis的EXISTS命令
     *
     * @param key
     * @return
     */
    public Boolean exists(String key) {
        return this.getRedisClient().exists(key);
    }

    /**
     * 执行Redis的TTL命令
     *
     * @param key
     * @return 当 key 不存在时，返回 -2, 当 key 存在但没有设置剩余生存时间时，返回 -1, 否则，以秒为单位，返回 key
     * 的剩余生存时间
     */
    public Long ttl(final String key) {
        return this.getRedisClient().ttl(key);
    }

    /**
     * 执行Redis的EXPIREAT命令
     *
     * @param key
     * @param unixTime
     * @return
     */
    public Long expireAt(final String key, final long unixTime) {
        return this.getRedisClient().expireAt(key, unixTime);
    }

    /* SortedSet(有序集合) */

    /**
     * 执行Redis的ZADD命令
     *
     * @param key
     * @param member
     * @return
     */
    public Long zadd(final String key, final Map<String, Double> scoreMembers) {
        return this.getRedisClient().zadd(key, scoreMembers);
    }

    /**
     * 执行Redis的ZADD命令
     *
     * @param key
     * @param member
     * @return
     */
    public Long zadd(final String key, final double score, final String member) {
        return this.getRedisClient().zadd(key, score, member);
    }

    /**
     * 执行Redis的ZRANGE命令 注意 start和end都是闭区间
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<String> zrange(final String key, final long start, final long end) {
        return this.getRedisClient().zrange(key, start, end);
    }

    /**
     * 执行Redis的ZRANGEBYSCORE命令, 注意min和max都是闭区间
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Set<String> zrangeByScore(final String key, final String min, final String max) {
        return this.getRedisClient().zrangeByScore(key, min, max);
    }

    /**
     * 执行Redis的ZRANGEBYSCORE命令
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Set<String> zrangeByScore(final String key, final double min, final double max) {
        return this.getRedisClient().zrangeByScore(key, min, max);
    }

    /**
     * 执行Redis的ZCARD命令
     *
     * @param key
     * @param member
     * @return
     */
    public Long zcard(final String key) {
        return this.getRedisClient().zcard(key);
    }

    /**
     * 执行Redis的ZCOUNT命令, 注意min和max都是闭区间
     *
     * @param key
     * @param member
     * @return
     */
    public Long zcount(final String key, final String min, final String max) {
        return this.getRedisClient().zcount(key, min, max);
    }

    /**
     * 执行Redis的ZCOUNT命令, 注意min和max都是闭区间
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Long zcount(final String key, final double min, final double max) {
        return this.getRedisClient().zcount(key, min, max);
    }

    /**
     * 执行Redis的ZREM命令
     *
     * @param key
     * @param member
     * @return
     */
    public Long zrem(final String key, final String... member) {
        return this.getRedisClient().zrem(key, member);
    }

    /**
     * 执行Redis的ZINCRBY命令
     *
     * @param key
     * @param score
     * @param member
     * @return
     */
    public Double zincrby(final String key, final double score, final String member) {
        return this.getRedisClient().zincrby(key, score, member);
    }

    /**
     * 执行Redis的ZRANK命令, 返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递增(从小到大)顺序排列
     *
     * @param key
     * @param member
     * @return 如果 member 是有序集 key 的成员，返回 member 的排名, 如果 member 不是有序集 key 的成员，返回
     * NULL
     */
    public Long zrank(final String key, final String member) {
        return this.getRedisClient().zrank(key, member);
    }

    /**
     * 执行Redis的ZSCORE命令, 返回有序集 key 中，成员 member 的 score 值
     *
     * @param key
     * @param member
     * @return member 成员的 score 值，以字符串形式表示, 如果不存在，返回NULL
     */
    public Double zscore(final String key, final String member) {
        return this.getRedisClient().zscore(key, member);
    }

    /**
     * 执行Redis的ZREVRANK命令
     *
     * @param key
     * @param member
     * @return
     */
    public Long zrevrank(final String key, final String member) {
        return this.getRedisClient().zrevrank(key, member);
    }

    /**
     * 执行Redis的ZREMRANGEBYSCORE命令
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Long zremrangeByScore(final String key, final double start, final double end) {
        return this.getRedisClient().zremrangeByScore(key, start, end);
    }

    /**
     * 执行Redis的ZREVRANGEBYSCORE命令
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<String> zrevrangeByScore(final String key, final double max, final double min) {
        return this.getRedisClient().zrevrangeByScore(key, max, min);
    }

    /**
     * 执行Redis的ZREVRANGEBYSCORE命令
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<String> zrevrangeByScore(final String key, final String max, final String min) {
        return this.getRedisClient().zrevrangeByScore(key, max, min);
    }

    /**
     * 执行Redis的ZREMRANGEBYRANK命令
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Long zremrangeByRank(final String key, final long start, final long end) {
        return this.getRedisClient().zremrangeByRank(key, start, end);
    }

    /**
     * 执行Redis的ZREVRANGE命令, 返回有序集 key 中，指定区间内的成员
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<String> zrevrange(final String key, final long start, final long end) {
        return this.getRedisClient().zrevrange(key, start, end);
    }

    /**
     * 求值
     *
     * @param script 脚本
     * @param keys   键列表
     * @param args   参数列表
     * @return 对象
     */
    public Object eval(final String script, final List<String> keys, final List<String> args) {
        return this.getRedisClient().eval(script, keys, args);
    }

    public RedisClientInterface getRedisClient() {
        return redisClient;
    }

    protected void setRedisClient(RedisClientInterface redisClient) {
        this.redisClient = redisClient;
    }


}
